gtktreeselection: Fix an abort on selecting an invalid range
authorPhilip Withnall <philip.withnall@collabora.co.uk>
Tue, 10 Mar 2015 08:26:34 +0000 (08:26 +0000)
committerPhilip Withnall <philip.withnall@collabora.co.uk>
Wed, 11 Mar 2015 11:24:29 +0000 (11:24 +0000)
gtk_tree_selection_real_modify_range() has a g_return_if_fail() if the
start or end paths passed to it do not correspond to real tree nodes.
However, GtkTreePaths inherently do not have to be valid, so it should
be acceptable to call gtk_tree_selection_select_range() with
non-existent paths. Replace the g_return_if_fail() by a silent return,
and add a unit test.

https://bugzilla.gnome.org/show_bug.cgi?id=712760

gtk/gtktreeselection.c
testsuite/gtk/treeview.c

index 1f6ae9b7e6529eb8447b871eaa95450361f1641a..b04bcc3e310ede5933bbefcbf98f39b964c15cdb 100644 (file)
@@ -1337,8 +1337,9 @@ gtk_tree_selection_real_modify_range (GtkTreeSelection *selection,
       break;
     }
 
-  g_return_val_if_fail (start_node != NULL, FALSE);
-  g_return_val_if_fail (end_node != NULL, FALSE);
+  /* Invalid start or end node? */
+  if (start_node == NULL || end_node == NULL)
+    return dirty;
 
   if (anchor_path)
     _gtk_tree_view_set_anchor_path (priv->tree_view, anchor_path);
index 499376eb1af5a3fbe3d689d7c4ef8ae417771317..758b52cc1a5c00800d03ac9d811eb7eb4ee8b542 100644 (file)
@@ -289,6 +289,60 @@ test_selection_count (void)
   gtk_widget_destroy (view);
 }
 
+static void
+abort_cb (GtkTreeModel *model,
+          GtkTreePath  *path,
+          GtkTreeIter  *iter,
+          gpointer      data)
+{
+  g_assert_not_reached ();
+}
+
+static void
+test_selection_empty (void)
+{
+  GtkTreePath *path;
+  GtkListStore *list_store;
+  GtkTreeSelection *selection;
+  GtkWidget *view;
+  GtkTreeIter iter;
+
+  g_test_bug ("712760");
+
+  list_store = gtk_list_store_new (1, G_TYPE_STRING);
+  view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (list_store));
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
+
+  g_assert_false (gtk_tree_selection_get_selected (selection, NULL, &iter));
+  gtk_tree_selection_selected_foreach (selection, abort_cb, NULL);
+  g_assert_null (gtk_tree_selection_get_selected_rows (selection, NULL));
+  g_assert_cmpint (gtk_tree_selection_count_selected_rows (selection), ==, 0);
+
+  path = gtk_tree_path_new_from_indices (0, -1);
+
+  gtk_tree_selection_select_path (selection, path);
+  gtk_tree_selection_unselect_path (selection, path);
+  g_assert_false (gtk_tree_selection_path_is_selected (selection, path));
+
+  gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
+
+  gtk_tree_selection_select_all (selection);
+  g_assert_cmpint (gtk_tree_selection_count_selected_rows (selection), ==, 0);
+
+  gtk_tree_selection_unselect_all (selection);
+  g_assert_cmpint (gtk_tree_selection_count_selected_rows (selection), ==, 0);
+
+  gtk_tree_selection_select_range (selection, path, path);
+  g_assert_cmpint (gtk_tree_selection_count_selected_rows (selection), ==, 0);
+
+  gtk_tree_selection_unselect_range (selection, path, path);
+  g_assert_cmpint (gtk_tree_selection_count_selected_rows (selection), ==, 0);
+
+  gtk_tree_path_free (path);
+
+  gtk_widget_destroy (view);
+}
+
 int
 main (int    argc,
       char **argv)
@@ -303,6 +357,7 @@ main (int    argc,
   g_test_add_func ("/TreeView/sizing/row-separator-height",
                    test_row_separator_height);
   g_test_add_func ("/TreeView/selection/count", test_selection_count);
+  g_test_add_func ("/TreeView/selection/empty", test_selection_empty);
 
   return g_test_run ();
 }